//
//  AZURLCache.m
//  AZNetwork
//
//  Created by GorXion on 2018/4/2.
//  Copyright © 2018年 gaoX. All rights reserved.
//

#import "AZURLCache.h"
#import "AZURLRequest.h"
#import <CommonCrypto/CommonDigest.h>

@interface AZURLCache ()

@property (nonatomic, strong) NSCache *memoryCache;

@end

@implementation AZURLCache

+ (instancetype)sharedURLCache
{
    static AZURLCache *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[AZURLCache alloc] init];
    });
    return instance;
}

- (void)storeCachedData:(id)data forRequest:(AZURLRequest *)request
{
    NSString *filePath = [self savedFilePathForRequest:request];
   
    [self.memoryCache setObject:data forKey:filePath];
    
    [NSKeyedArchiver archiveRootObject:data toFile:filePath];
}

- (id)cachedDataForRequest:(AZURLRequest *)request
{
    NSString *filePath = [self savedFilePathForRequest:request];
    
    id cachedData = [self.memoryCache objectForKey:filePath];
    if (!cachedData) return cachedData;
    
    return [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
}

- (void)removeCachedDataForRequest:(AZURLRequest *)request
{
    NSString *filePath = [self savedFilePathForRequest:request];
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
    }
}

- (void)removeAllCachedData
{
    NSString *cachedPath = [self cachedPath];
    if ([[NSFileManager defaultManager] fileExistsAtPath:cachedPath]) {
        [[NSFileManager defaultManager] removeItemAtPath:cachedPath error:nil];
    }
}

#pragma mark - private
- (NSString *)savedFilePathForRequest:(AZURLRequest *)request
{
    NSMutableArray *params = @[].mutableCopy;
    [request.parameters enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        NSString *param = [NSString stringWithFormat:@"%@=%@", key, obj];
        [params addObject:param];
    }];
    NSString *parameters = [params componentsJoinedByString:@"&"];
    NSString *filePath = [NSString stringWithFormat:@"%@?%@", request.URLString, parameters];
    NSString *cachedPath = [self cachedPath];
    return [cachedPath stringByAppendingPathComponent:[self convertToMD5String:filePath]];
}

- (NSString *)convertToMD5String:(NSString *)string
{
    const char *cStr = [string UTF8String];
    unsigned char result[16];
    CC_MD5(cStr, (unsigned int) strlen(cStr), result);
    NSString *md5String = [NSString stringWithFormat:
                           @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                           result[0], result[1], result[2], result[3],
                           result[4], result[5], result[6], result[7],
                           result[8], result[9], result[10], result[11],
                           result[12], result[13], result[14], result[15]
                           ];
    return md5String;
}

- (NSString *)cachedPath
{
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    NSString *cachedPath = [path stringByAppendingPathComponent:@"AZNetworkRequestCache"];
    [self checkDirectory:cachedPath];
    return cachedPath;
}

- (void)checkDirectory:(NSString *)path
{
    BOOL isDir;
    if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
        [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
    }
    else {
        if (!isDir) {
            [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
            [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
        }
    }
}

#pragma mark - getter
- (NSCache *)memoryCache
{
    if (!_memoryCache) {
        _memoryCache = [[NSCache alloc] init];
    }
    return _memoryCache;
}

@end
